﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Web.Script.Serialization;

namespace YoutubeDownloader
{
    public class Finder
    {
        public enum SearchStep
        {
            Started,
            DownloadingPageStarted,
            DownloadingPageEnded,
            ParsingPage,
            ItemAdded,
            Ended
        }

        public delegate void SearchProgressDelegate(SearchStep step, object param1, object param2);

        public bool Search(List<string> authors, string period, SearchProgressDelegate searchDelegate)
        {
            foreach (string author in authors)
            {
                List<Video> videoList = new List<Video>();
                int startIndex = 1;
                int videoCount = 1;

                try
                {
                    searchDelegate.Invoke(SearchStep.Started, author, null);
                    do
                    {
                        string url = "http://gdata.youtube.com/feeds/api/videos?author=" + author + "&v=2&alt=jsonc&max-results=40&start-index=" + startIndex + "&time=" + period.ToLower();
                        searchDelegate.Invoke(SearchStep.DownloadingPageStarted, url, startIndex);
                        Dictionary<string, object> youtube = (Dictionary<string, object>)new JavaScriptSerializer().DeserializeObject(DownloadWebPage(url));
                        searchDelegate.Invoke(SearchStep.DownloadingPageEnded, url, startIndex);

                        startIndex += 25;

                        if (youtube.ContainsKey("data"))
                        {
                            Dictionary<string, object> youtubeHeader = (Dictionary<string, object>)youtube["data"];

                            int currentStartIndex = (int)youtubeHeader["startIndex"];
                            int currentTotalItems = (int)youtubeHeader["totalItems"];

                            if (currentStartIndex > currentTotalItems)
                            {
                                Console.WriteLine("No more video to add.");
                                break;
                            }

                            foreach (object item in (object[])youtubeHeader["items"])
                            {
                                try
                                {
                                    if (item is Dictionary<string, object>)
                                    {
                                        Video v = new Video(item as Dictionary<string, object>);
                                        videoList.Add(v);
                                        searchDelegate.Invoke(SearchStep.ItemAdded, v, (int)(videoCount * 100 / currentTotalItems));
                                        videoCount++;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Debug.WriteLine("Can't serialize item, ex: " + ex);
                                    break;
                                }
                            }
                        }

                    } while (true);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Search failed: " + ex.Message);
                }
                
            }
            searchDelegate.Invoke(SearchStep.Ended, null, null);
            return true;
        }

        public static string DownloadWebPage(string url)
        {
            HttpWebRequest webRequestObject = (HttpWebRequest)HttpWebRequest.Create(url);

            // You can also specify additional header values like 
            // the user agent or the referer:
            webRequestObject.UserAgent = "Internet Explorer 5.0";
            webRequestObject.Referer = "http://wwW.youtube.com";

            // Request response:
            WebResponse webResponse = webRequestObject.GetResponse();

            // Open data stream:
            Stream webStream = webResponse.GetResponseStream();

            // Create reader object:
            StreamReader streamReader = new StreamReader(webStream);

            // Read the entire stream content:
            string pageContent = streamReader.ReadToEnd();

            // Cleanup
            streamReader.Close();
            webStream.Close();
            webResponse.Close();

            return pageContent;
        }
    }
}
